/*
 * @Author: 熊燕萍
 * @Date: 2021-02-23 09:40:52
 * @LastEditors: 杨道博
 * @LastEditTime: 2021-12-31 10:51:13
 * @Description: file content
 * @FilePath: \ys.ezJcyj\src\ys\map\interaction.js
 */
import { Draw } from 'ol/interaction';
import Vector from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector';
import { Fill, Stroke, Style, Circle, Icon } from 'ol/style';
import Overlay from 'ol/Overlay';
import { getArea, getLength } from 'ol/sphere'
import { unByKey } from 'ol/Observable';
import LineString from 'ol/geom/LineString';
import Point from 'ol/geom/Point';
import Polygon from 'ol/geom/Polygon';
import { createBox } from 'ol/interaction/Draw';

function Interaction(map) {
  this.map = map;
}
/**
 * @description: 手动绘制图形
 * @param {string} geometryType 绘图类型：'LineString'，'Polygon','Circle','Rect'
 * @param {Function} drawEndCall 绘制完成的回调事件
 * @param {boolean} single 每次只绘制一个，绘制时清除上一次绘制的图形,默认为true,如果为false可连续绘制多个图形
 * @param {object} styleObj 绘制图形的样式
 * @return {*}
 */
Interaction.prototype.drawGeometry=function(geometryType,drawEndCall,single=true,styleObj={}) {
  if (this.draw) {
      this.map.removeInteraction(this.draw); //移除上一次绘制事件
      this.draw = null;
  }
  if(!this.drawLayer){//图层未创建
      this.drawLayer = new Vector({
          source: new VectorSource({wrapX: false}),
          zIndex: 900,
          style: new Style({ //图层样式
            fill: new Fill({
              color: styleObj.fillColor||'rgba(255, 255, 255, 0.2)' //填充颜色
            }),
            stroke: new Stroke({
              color: styleObj.strokeColor||'#ffcc33',  //边框颜色
              width: styleObj.strokeWidth||3   // 边框宽度
            }),
            image: new Circle({
              radius: 7,
              fill: new Fill({
                  color: '#ffcc33'
              })
            })
          })
        });
        this.map.addLayer(this.drawLayer);
  }
  else{
      if(single){
          this.drawLayer.getSource().clear();
      }
  }
  if(geometryType=='Rect'){//如果是绘制矩形
      this.draw = new Draw({
          type: 'Circle',
          source: this.drawLayer.getSource(),    // 注意设置source，这样绘制好的线，就会添加到这个source里
          geometryFunction: createBox()
      });
  }
  else{//其他图形
      this.draw = new Draw({
          type: geometryType||'LineString',
          source: this.drawLayer.getSource(),    // 注意设置source，这样绘制好的线，就会添加到这个source里
          // style: new Style({            // 设置绘制时的样式
          //     stroke: new Stroke({
          //         color: '#009933',
          //         size: 1
          //     })
          // }),
          //maxPoints: 4    // 限制不超过4个点
      });
  }
  
  this.map.addInteraction(this.draw);
  let _this=this;
  // 监听线绘制结束事件，获取坐标
  this.draw.on('drawend', function(evt){
     if(single){
      _this.map.removeInteraction(_this.draw); //移除绘制事件
      _this.draw = null;
     } 
     let coordinates=evt.feature.getGeometry().getCoordinates();
     drawEndCall(coordinates,evt);//结束绘制回调事件
  });
}
/**
* @description: 清除绘图的相关事件
* @return {*}
*/
Interaction.prototype.removeDrawGeometry=function() {
  if (this.draw) {
      this.map.removeInteraction(this.draw); //移除上一次绘制事件
      this.draw = null;
  }
  if(this.drawLayer){
      this.map.removeLayer(this.drawLayer);
      this.drawLayer=null;  
  }
}
/**
 * @description: 手动绘制图形-监测点
 * @param {string} geometryType 绘图类型：'LineString'，'Polygon','Circle','Rect'
 * @param {Function}  绘制完成的回调事件
 * @param {boolean} single 每次只绘制一个，绘制时清除上一次绘制的图形,默认为true,如果为false可连续绘制多个图形
 * @param {object} styleObj 绘制图形的样式
 * @return {*}
 */
Interaction.prototype.drawGeometryjcd = function (layer, geometryType,single = true, styleObj = {}, index) {
  if (this.draw) {
    this.map.removeInteraction(this.draw); //移除上一次绘制事件
    this.draw = null;
  }
  if (!this.drawLayerjcd) {//图层未创建
    this.drawLayerjcd = {
      drawlineLayers: null, //边界
      drawjtLayer: null, //箭头
      drawqyLayer: null, //区域
      drawpmxLayer: null //剖面线
    }
  }
  if (!this.drawLayerjcd[layer]) {//图层未创建
    this.drawLayerjcd[layer] = new Vector({
      source: new VectorSource({ wrapX: false }),
      zIndex: 900,
    })
    this.map.addLayer(this.drawLayerjcd[layer]);
  }
  // else {
  //   // if (single) {
  //   //   this.drawLayer.getSource().clear();
  //   // }
  // }
  this.drawLayerjcd[layer].setStyle(index == 1 ? stylejtFunction : styleFuction(styleObj))
  if (geometryType == 'Rect') {//如果是绘制矩形
    this.draw = new Draw({
      type: 'Circle',
      source: this.drawLayerjcd[layer].getSource(),    // 注意设置source，这样绘制好的线，就会添加到这个source里
      geometryFunction: createBox()
    });
  } else {//其他图形
    this.draw = new Draw({
      type: geometryType || 'LineString',
      source: this.drawLayerjcd[layer].getSource(),    // 注意设置source，这样绘制好的线，就会添加到这个source里
      style: new Style({            // 设置绘制时的样式
          stroke: new Stroke({
              color: '#F56C6C',
              size: 1
          })
      }),
      maxPoints: 4    // 限制不超过4个点
    });
  }
  this.map.addInteraction(this.draw);
  let _this = this;
  // 监听线绘制结束事件，获取坐标
  this.draw.on('drawend', function (evt) {
    if (single) {
      _this.map.removeInteraction(_this.draw); //移除绘制事件
      _this.draw = null;
    }
    let coordinates = evt.feature.getGeometry().getCoordinates();
    drawEndCall(coordinates, _this.drawLayerjcd[layer], evt);//结束绘制回调事件
  });
}
let styleFuction = function (styleObj) {
  var style = new Style({ //图层样式
    fill: new Fill({
      color: styleObj.fillColor || 'rgba(255, 255, 255, 0.2)' //填充颜色
    }),
    stroke: new Stroke({
      color: styleObj.strokeColor || '#ffcc33',  //边框颜色
      width: styleObj.strokeWidth || 3   // 边框宽度
    }),
    image: new Circle({
      radius: 7,
      fill: new Fill({
        color: '#ffcc33'
      })
    })
  })
  return style;
}
let stylejtFunction = function (feature) {
  var geometry = feature.getGeometry();
  var styles = [
    // linestring
    new Style({
      stroke: new Stroke({
        color: '#ffcc33',
        width: 2,
      }),
    })];

  geometry.forEachSegment(function (start, end) {
    var dx = end[0] - start[0];
    var dy = end[1] - start[1];
    var rotation = Math.atan2(dy, dx);
    // arrows
    styles.push(
      new Style({
        geometry: new Point(end),
        image: new Icon({
          src: './arrow.png',
          anchor: [0.75, 0.5],
          rotateWithView: true,
          rotation: -rotation,
        }),
      })
    );
  });

  return styles;
};
/**
 * @description: 清除绘图的相关事件
 * @return {*}
 */
Interaction.prototype.removeDrawGeometryjcd = function (arr) {
  if (this.draw) {
    this.map.removeInteraction(this.draw); //移除上一次绘制事件
    this.draw = null;
  }
  //遍历去掉所有图层
  let _this = this
  arr.forEach(function (item) {
    if (_this.drawLayerjcd[item.name]) {
      _this.map.removeLayer(_this.drawLayerjcd[item.name]);
      _this.drawLayerjcd[item.name] = null;
    }
  })

}

/**
 * @description: 测量功能：测距、测面积
 * @param {string} typeSelect LineString测距离 Polygon测面积
 * @param {object} styleObj 绘制后图形样式
 * @return {*}
 */
Interaction.prototype.mesureTool = function (typeSelect, styleObj = {}) {
  var measureTooltipElement = null;
  var measureTooltip = null;

  if (this.draw) {
    this.map.removeInteraction(this.draw); //移除上一次绘制事件
    this.draw = null;
  }
  if (!this.mesureLayer) {//图层未创建
    this.mesureLayer = new Vector({
      source: new VectorSource({ wrapX: false }),
      zIndex: 900,
      style: new Style({ //图层样式
        fill: new Fill({
          color: styleObj.fillColor || 'rgba(255, 255, 255, 0.2)' //填充颜色
        }),
        stroke: new Stroke({
          color: styleObj.strokeColor || '#ffcc33',  //边框颜色
          width: styleObj.strokeWidth || 2   // 边框宽度
        }),
        // image: new Circle({
        //   radius: 7,
        //   fill: new Fill({
        //     color: '#ffcc33'
        //   })
        // })
      })
    });
    this.map.addLayer(this.mesureLayer);
  }
  let type = (typeSelect == 'Polygon' ? 'Polygon' : 'LineString');
  this.draw = new Draw({
    source: this.mesureLayer.getSource(),//测量绘制层数据源
    type: type,  //几何图形类型ol.geom.GeometryType
    style: new Style({//绘制几何图形的样式
      fill: new Fill({
        color: 'rgb(255, 204, 51,0.2)'
      }),
      stroke: new Stroke({
        color: 'rgb(255, 204, 51)',
        lineDash: [10, 10],
        width: 2
      }),
      image: new Circle({
        radius: 5,
        stroke: new Stroke({
          color: 'rgb(255,204,51)'
        }),
        fill: new Fill({
          color: 'rgba(255, 255, 255, 0.2)'
        })
      })
    })
  });
  this.map.addInteraction(this.draw);
  createMeasureTooltip(this.map); //创建测量工具提示框
  let listener;
  let sketch;
  //绑定交互绘制工具开始绘制的事件
  let _this = this;
  this.draw.on('drawstart', function (evt) {
    sketch = evt.feature; //绘制的要素

    let tooltipCoord = evt.coordinate;// 绘制的坐标
    //绑定change事件，根据绘制几何类型得到测量长度值或面积值，并将其设置到测量工具提示框中显示
    listener = sketch.getGeometry().on('change', function (evt) {
      let geom = evt.target;//绘制几何要素
      let output;
      if (geom instanceof Polygon) {
        output = formatArea(_this.map, geom);//面积值
        tooltipCoord = geom.getInteriorPoint().getCoordinates();//坐标
      } else if (geom instanceof LineString) {
        output = formatLength(_this.map, geom);//长度值
        tooltipCoord = geom.getLastCoordinate();//坐标
      }
      measureTooltipElement.innerHTML = output;//将测量值设置到测量工具提示框中显示
      measureTooltip.setPosition(tooltipCoord);//设置测量工具提示框的显示位置
    });
  }, this);
  //绑定交互绘制工具结束绘制的事件
  this.draw.on('drawend', function (evt) {
    measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'; //设置测量提示框的样式
    let closebtn = document.createElement('span');
    closebtn.className = 'ol-measure-clear';
    closebtn.innerHTML = '×';
    closebtn.onclick = function () {
      _this.mesureLayer.getSource().removeFeature(evt.feature);
      closebtn.parentNode.parentNode.remove();
    };
    measureTooltipElement.appendChild(closebtn);
    measureTooltip.setOffset([0, -7]);
    // unset sketch
    sketch = null; //置空当前绘制的要素对象
    measureTooltipElement = null; //置空测量工具提示框对象
    createMeasureTooltip(_this.map);//重新创建一个测试工具提示框显示结果
    unByKey(listener);
    _this.map.removeInteraction(_this.draw); //移除上一次绘制事件
    this.draw = null;
  }, this);

  /**
   *创建一个新的测量工具提示框（tooltip）
   */
  function createMeasureTooltip(map) {
    if (measureTooltipElement) {
      measureTooltipElement.parentNode.removeChild(measureTooltipElement);
    }
    measureTooltipElement = document.createElement('div');
    measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure';
    measureTooltip = new Overlay({
      element: measureTooltipElement,
      offset: [0, -15],
      positioning: 'bottom-center'
    });
    map.addOverlay(measureTooltip);
  }

  /**
   * 测量长度输出
   * @param {ol.geom.LineString} line
   * @return {string}
   */
  function formatLength(map, line) {
    let sourceProj = map.getView().getProjection();//获取投影坐标系
    let length = getLength(line, { projection: sourceProj });
    let output;
    if (length > 100) {
      output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km';
    } else {
      output = (Math.round(length * 100) / 100) + ' ' + 'm';
    }
    return output;
  }

  /**
   * 测量面积输出
   * @param {ol.geom.Polygon} polygon
   * @return {string}
   */
  function formatArea(map, polygon) {
    let sourceProj = map.getView().getProjection();//获取投影坐标系
    let area = getArea(polygon, { projection: sourceProj });
    let output;
    if (area > 10000) {
      output = (Math.round(area / 1000000 * 100) / 100) +
        ' ' + 'km<sup>2</sup>';
    } else {
      output = (Math.round(area * 100) / 100) +
        ' ' + 'm<sup>2</sup>';
    }
    return output;
  }
}

/**
 * @description: 清除测量功能相关事件
 * @param {*}
 * @return {*}
 */
Interaction.prototype.removeMesureTool = function () {
  if (this.draw) {
    this.map.removeInteraction(this.draw); //移除上一次绘制事件
    this.draw = null;
  }
  if (this.mesureLayer) {
    this.map.removeLayer(this.mesureLayer);
    this.mesureLayer = null;
  }
  document.querySelectorAll('.ol-tooltip').forEach(e => e.remove());
}
//获取鼠标点击生成的像素坐标
Interaction.prototype.getJwd=function(vm){
  this.map.on('click', function (event) {
    console.log(event)
    var coordinate = event.coordinate; // 点击位置的经纬度坐标
    vm.coordinate = event.coordinate
    vm.pixel = event.map.getPixelFromCoordinate(coordinate)
});
}
export default Interaction
